/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
package org.unidata.mdm.dq.core.dao.impl;

import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.unidata.mdm.dq.core.dao.DataQualityDAO;
import org.unidata.mdm.dq.core.po.DataQualityPO;
import org.unidata.mdm.system.dao.impl.BaseDAOImpl;

/**
 * @author Mikhail Mikhailov on Oct 1, 2020
 * DQ model CRUD.
 */
@Repository
public class DataQualityDAOImpl extends BaseDAOImpl implements DataQualityDAO {
    /**
     * Default SSPO row mapper.
     */
    private static final RowMapper<DataQualityPO> DEFAULT_ROW_MAPPER = (rs, row) -> {

        DataQualityPO result = new DataQualityPO();
        result.setStorageId(rs.getString(DataQualityPO.FIELD_STORAGE_ID));
        result.setRevision(rs.getInt(DataQualityPO.FIELD_REVISION));
        result.setOperationId(rs.getString(DataQualityPO.FIELD_OPERATION_ID));
        result.setDescription(rs.getString(DataQualityPO.FIELD_DESCRIPTION));
        result.setCreatedBy(rs.getString(DataQualityPO.FIELD_CREATED_BY));
        result.setCreateDate(rs.getTimestamp(DataQualityPO.FIELD_CREATE_DATE));
        result.setContent(rs.getBytes(DataQualityPO.FIELD_CONTENT));

        return result;
    };
    /**
     * Queries.
     */
    private final String lastSQL;
    private final String currentSQL;
    private final String previousSQL;
    private final String loadSQL;
    private final String saveSQL;
    private final String removeSQL;
    /**
     * Constructor.
     */
    @Autowired
    public DataQualityDAOImpl(
            @Qualifier("dataQualityDataSource") final DataSource dataSource,
            @Qualifier("dq-model-sql") final Properties sql) {
        super(dataSource);
        lastSQL = sql.getProperty("lastSQL");
        currentSQL = sql.getProperty("currentSQL");
        previousSQL = sql.getProperty("previousSQL");
        loadSQL = sql.getProperty("loadSQL");
        saveSQL = sql.getProperty("saveSQL");
        removeSQL = sql.getProperty("removeSQL");
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public int latest(String storageId) {
        return getJdbcTemplate().query(lastSQL, rs -> rs.next() ? rs.getInt(DataQualityPO.FIELD_REVISION) : 0, storageId);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public DataQualityPO current(String storageId) {
        return getJdbcTemplate().query(currentSQL, rs -> rs.next() ? DEFAULT_ROW_MAPPER.mapRow(rs, 0) : null, storageId);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public DataQualityPO previous(String storageId, int revision) {
        return getJdbcTemplate().query(previousSQL, rs -> rs.next() ? DEFAULT_ROW_MAPPER.mapRow(rs, 0) : null, storageId, revision);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public List<DataQualityPO> load(String storageId, int from, int count, boolean withData) {
        return getJdbcTemplate().query(loadSQL, DEFAULT_ROW_MAPPER, withData, storageId, from, count);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public int save(DataQualityPO po) {
        return getJdbcTemplate().queryForObject(saveSQL, Integer.class,
                po.getStorageId(),
                po.getRevision(),
                po.getDescription(),
                po.getOperationId(),
                po.getContent(),
                po.getCreatedBy());
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void remove(String storageId, int revision) {
        getJdbcTemplate().update(removeSQL, storageId, revision);
    }
}
